package meng.study.fastdfs.client;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.ProtoCommon;
import org.csource.fastdfs.StorageClient1;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;

public class FastDFSClient {

	private static final String CONFIG_FILENAME = "src/main/resources/fdfs/fdfs_client.conf";

	private static StorageClient1 storageClient1 = null;
	private static boolean anti_steal_token = false;
	private static String secret_key = "";

	// 初始化FastDFS Client
	static {
		try {
			ClientGlobal.init(CONFIG_FILENAME);
			TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
			TrackerServer trackerServer = trackerClient.getConnection();
			if (trackerServer == null) {
				throw new IllegalStateException("getConnection return null");
			}

			StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
			if (storageServer == null) {
				throw new IllegalStateException("getStoreStorage return null");
			}

			storageClient1 = new StorageClient1(trackerServer, storageServer);
			// 防盗链
			anti_steal_token = ClientGlobal.g_anti_steal_token;
			secret_key = ClientGlobal.g_secret_key;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 上传文件
	 * 
	 * @param file
	 *            文件对象
	 * @param fileName
	 *            文件名
	 * @return
	 */
	public static String uploadFile(File file) {
		return uploadFile(file, file.getName(), null);
	}

	/**
	 * 上传文件
	 * 
	 * @param file
	 *            文件对象
	 * @param fileName
	 *            文件名
	 * @param metaList
	 *            文件元数据
	 * @return
	 */
	public static String uploadFile(File file, String fileName, Map<String, String> metaList) {
		try {
			byte[] buff = IOUtils.toByteArray(new FileInputStream(file));
			NameValuePair[] nameValuePairs = null;
			if (metaList != null) {
				nameValuePairs = new NameValuePair[metaList.size()];
				int index = 0;
				for (Iterator<Map.Entry<String, String>> iterator = metaList.entrySet().iterator(); iterator
						.hasNext();) {
					Map.Entry<String, String> entry = iterator.next();
					String name = entry.getKey();
					String value = entry.getValue();
					nameValuePairs[index++] = new NameValuePair(name, value);
				}
			}

			String uploadFilePath = storageClient1.upload_file1(buff, FilenameUtils.getExtension(fileName),
					nameValuePairs);
			if (anti_steal_token) {
				int ts = (int) (System.currentTimeMillis() / 1000);
				String path = uploadFilePath.substring(7);
				String token = getToken(path, ts);
				return uploadFilePath + "?token=" + token + "&ts=" + ts;
			} else {
				return uploadFilePath;
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取文件元数据
	 * 
	 * @param fileId
	 *            文件ID
	 * @return
	 */
	public static Map<String, String> getFileMetadata(String fileId) {
		try {
			NameValuePair[] metaList = storageClient1.get_metadata1(fileId);
			if (metaList != null) {
				HashMap<String, String> map = new HashMap<String, String>();
				for (NameValuePair metaItem : metaList) {
					map.put(metaItem.getName(), metaItem.getValue());
				}
				return map;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 删除文件
	 * 
	 * @param fileId
	 *            文件ID
	 * @return 删除失败返回-1，否则返回0
	 */
	public static int deleteFile(String fileId) {
		try {
			return storageClient1.delete_file1(fileId);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return -1;
	}

	/**
	 * 下载文件
	 * 
	 * @param fileId
	 *            文件ID（上传文件成功后返回的ID）
	 * @param outFile
	 *            文件下载保存位置
	 * @return
	 */
	public static int downloadFile(String fileId, File outFile) {
		FileOutputStream fos = null;
		try {
			byte[] content = storageClient1.download_file1(fileId);
			fos = new FileOutputStream(outFile);
			IOUtils.write(content, fos);
			return 0;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return -1;
	}

	/**
	 * 
	 * @param filename
	 *            filename 指的是上传时候分配的file名
	 *            如：M00/00/00/Csj8oVeFt6OATXSVABkMwmX6qlY849.txt 注意：去除group[0-9]
	 * @param ts
	 *            time是秒级的
	 * @return token 如:29e1e3eaa1a05b9fcda9a0449922e492
	 */
	public static String getToken(String filename, int ts) {
		// int ts = (int) (System.currentTimeMillis()/1000);

		String token = "";
		try {
			token = ProtoCommon.getToken(filename, ts, ClientGlobal.getG_secret_key());
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (MyException e) {
			e.printStackTrace();
		}
		return token;
	}
}
